import flask
import json
from flask import jsonify, Response, request
from functools import wraps
from biz.core.sql.generator import intercept_sql
from biz.config.settings import cache, get_sql_context, \
    get_command_context, get_sql_function_context
from biz.core.functions import generate_sql_core, generate_command_core, generate_answer_core, generate_diagnosis_core, generate_answer_core_multi_agent
from biz.utils.logger import logger
from biz.data.dashboard import DashboardService
from biz.utils.jwt_util import JwtUtil

# 初始化全局变量
vn = get_sql_context()
vn_command = get_command_context()
sql_function_context = get_sql_function_context()
dashboard_service = DashboardService()
jwt_util = JwtUtil()

def get_user_info_from_request(request):
    """
    从请求中获取用户信息
    """
    try:
        # 从请求头中获取token
        token = request.headers.get('x-Authentication-Token')
        if not token:
            return None
        
        # 解析JWT token
        user_info = jwt_util.parse_jwt(token)
        if user_info:
            return {
                'organ_ids': user_info.get('organ_ids',[]),
                'user_id': user_info.get('user_id'),
                'username': user_info.get('username')
            }
        else:
            return None
    except Exception as e:
        logger.error(f"获取用户信息失败: {str(e)}")
        # 出错时返回默认信息
        return None
def requires_cache(fields):
    def decorator(f):
        @wraps(f)
        def decorated(*args, **kwargs):
            id = request.args.get('id')

            if id is None:
                return jsonify({"type": "error", "error": "No id provided"})
            
            for field in fields:
                if cache.get(id=id, field=field) is None:
                    return jsonify({"type": "error", "error": f"No {field} found"})
            
            field_values = {field: cache.get(id=id, field=field) for field in fields}
            
            # Add the id to the field_values
            field_values['id'] = id

            return f(*args, **field_values, **kwargs)
        return decorated
    return decorator

def register_routes(app):
    @app.route('/api/v0/generate_questions', methods=['GET'])
    def generate_questions():
        return jsonify({
            "type": "question_list", 
            "questions": vn.generate_questions(),
            "header": "以下是您可以问的一些问题："
            })

    @app.route('/api/v0/generate_sql', methods=['GET', 'POST'])
    def generate_sql():
        # 支持GET和POST两种方式
        if flask.request.method == 'GET':
            question = flask.request.args.get('question')
            id = flask.request.args.get('id', None)
            stream = flask.request.args.get('stream', 'false').lower() == 'true'
            filter_conditions = {}
        else:  # POST方法
            data = flask.request.get_json() or {}
            question = data.get('question')
            id = data.get('id', None)
            stream = data.get('stream', False)
            filter_conditions = data.get('filters', {})
        
        if question is None:
            return jsonify({"type": "error", "error": "没有提供问题"})
        if id is None:
            id = cache.generate_id(question=question)

        # 获取用户信息（这里需要根据实际的认证机制来获取）
        user_info = get_user_info_from_request(flask.request)
        # 统一构建过滤条件
        if user_info:
            if 'organ_ids' in user_info and user_info['organ_ids']:
                filter_conditions['organ_ids'] = user_info['organ_ids']

        # 流式响应
        if stream:
            def generate():
                try:
                    from biz.core.functions import generate_sql_stream
                    import json
                    for chunk in generate_sql_stream(question, id, filter_conditions=filter_conditions):
                        yield f"data: {json.dumps(chunk, ensure_ascii=False)}\n\n"
                except Exception as e:
                    yield f"data: {json.dumps({'type': 'error', 'error': str(e)}, ensure_ascii=False)}\n\n"
            
            return flask.Response(generate(), mimetype='text/event-stream')
        
        # 完整响应（默认行为）
        id, sql = generate_sql_core(question, id, filter_conditions=filter_conditions)
        return jsonify(
            {
                "type": "sql", 
                "id": id,
                "text": sql,
            })

    @app.route('/api/v0/run_sql', methods=['GET'])
    @requires_cache(['sql'])
    def run_sql(id: str, sql: str):
        try:
            intercept_sql(sql)
            df = vn.run_sql(sql=sql)
             # 处理时间戳列
            for col in df.select_dtypes(include=['datetime64']).columns:
                df[col] = df[col].dt.strftime('%Y-%m-%d %H:%M:%S')
            
            # 处理object类型的日期列，避免转换为时间戳
            for col in df.select_dtypes(include=['object']).columns:
                if df[col].dtype == 'object':
                    # 检查是否为日期类型
                    try:
                        import pandas as pd
                        # 尝试转换为datetime，如果成功说明是日期类型
                        sample_val = df[col].dropna().iloc[0] if not df[col].dropna().empty else None
                        if sample_val is not None and pd.to_datetime(sample_val, errors='coerce') is not pd.NaT:
                            df[col] = pd.to_datetime(df[col], errors='coerce').dt.strftime('%Y-%m-%d %H:%M:%S')
                    except:
                        pass
            
            # 处理null
            df = df.fillna('')
            
            cache.set(id=id, field='df', value=df)
            response_data = {
                "type": "df", 
                "id": id,
                "df": df.to_json(orient='records', date_format='iso', force_ascii=False),
            }
            response = flask.Response(
                json.dumps(response_data, ensure_ascii=False, indent=2),
                mimetype='application/json; charset=utf-8'
            )
            return response
        except Exception as e:
            import traceback
            traceback.print_exc()
            question = cache.get(id=id, field='question')
            logger.error(f"问题：{question}\nSQL：{sql}")
            error_message = str(e)
            #new_sql = generate_sql_core(question=f"sql运行报错，请根据错误信息重新生成sql，错误信息：{error_message}", id=id)
            #print(new_sql)
            return jsonify({"type": "error", "error": "执行SQL出错，请检查SQL语句"})

    @app.route('/api/v0/download_csv', methods=['GET'])
    @requires_cache(['df'])
    def download_csv(id: str, df):
        csv = df.to_csv()
        return Response(
            csv,
            mimetype="text/csv",
            headers={"Content-disposition":
                     f"attachment; filename={id}.csv"})

    @app.route('/api/v0/generate_plotly_figure', methods=['GET'])
    @requires_cache(['df', 'question', 'sql'])
    def generate_plotly_figure(id: str, df, question, sql):
        try:
            # 获取 dark_mode 参数，默认为 False
            dark_mode = flask.request.args.get('dark_mode', 'false').lower() == 'true'
            if len(df) == 0:
                return jsonify({"type": "error", "error": "没有数据"})
            code = vn.generate_plotly_code(question=question, sql=sql, df=df)
            print(code)
            fig = vn.get_plotly_figure(plotly_code=code, df=df, dark_mode=dark_mode)
            # 判断是否为散点图
            is_scatter = any(
                trace.type in ['scatter', 'scattergl'] and 
                ('markers' in getattr(trace, 'mode', '') and 'lines' not in getattr(trace, 'mode', '') or getattr(trace, 'mode', '') == 'markers')
                for trace in fig.data)
            if is_scatter:
                return jsonify({"type": "error", "error": "不适合可视化"})

            fig_json = fig.to_json()
            cache.set(id=id, field='fig_json', value=fig_json)
            return jsonify(
                {
                    "type": "plotly_figure",
                    "id": id,
                    "fig": fig_json,
                })
        except Exception as e:
            # Print the stack trace
            import traceback
            traceback.print_exc()
            return jsonify({"type": "error", "error": "不适合可视化"})

    @app.route('/api/v0/get_training_data', methods=['GET'])
    def get_training_data():
        df = vn.get_training_data()
        return jsonify(
        {
            "type": "df", 
            "id": "training_data",
            "df": df.head(200).to_json(orient='records'),
        })

    @app.route('/api/v0/remove_training_data', methods=['POST'])
    def remove_training_data():
        # Get id from the JSON body
        id = flask.request.json.get('id')
        if id is None:
            return jsonify({"type": "error", "error": "No id provided"})
        if vn.remove_training_data(id=id):
            return jsonify({"success": True})
        else:
            return jsonify({"type": "error", "error": "Couldn't remove training data"})

    @app.route('/api/v0/train', methods=['POST'])
    def add_training_data():
        question = flask.request.json.get('question')
        sql = flask.request.json.get('sql')
        ddl = flask.request.json.get('ddl')
        documentation = flask.request.json.get('documentation')

        try:
            id = vn.train(question=question, sql=sql, ddl=ddl, documentation=documentation)
            return jsonify({"id": id})
        except Exception as e:
            print("TRAINING ERROR", e)
            return jsonify({"type": "error", "error": str(e)})



    @app.route('/api/v0/sql_templates', methods=['POST'])
    def add_sql_template():
        """添加 SQL 模板"""
        try:
            data = flask.request.json
            if not data:
                return jsonify({"type": "error", "error": "请提供 JSON 数据"})

            id = data.get('id')
            description = data.get('description')
            sql_template = data.get('sql_template')
            parameters_data = data.get('parameters', [])
            
            # 如果parameters是列表或字典，转换为JSON字符串；如果已经是字符串，直接使用
            if isinstance(parameters_data, (list, dict)):
                parameters = json.dumps(parameters_data, ensure_ascii=False)
            else:
                parameters = parameters_data or '[]'
                
            plotly_code = data.get('plotly_code') or ''

            if not id or not description or not sql_template:
                return jsonify({
                    "type": "error",
                    "error": "id, description 和 sql_template 是必填字段"
                })
            template = sql_function_context.get_function_by_id(id=id)
            if template:
                sql_function_context.delete_function(id=id)
            # 添加 SQL 模板
            result_id = sql_function_context.create_function(
                id=id,
                description=description,
                sql_template=sql_template,
                parameters=parameters,
                plotly_code=plotly_code
            )

            return jsonify({
                "type": "success",
                "message": "SQL 模板添加成功",
                "template_id": result_id
            })

        except Exception as e:
            return jsonify({"type": "error", "error": f"添加模板失败: {str(e)}"})


    @app.route('/api/v0/list_all_sql_templates', methods=['GET'])
    def list_all_sql_templates():
        df = sql_function_context.list_functions()
        return jsonify(
            {
                "type": "df",
                "id": "sql_templates",
                "df": json.loads(df.to_json(orient='records')),
            })

    @app.route('/api/v0/sql_templates/<id>', methods=['PUT'])
    def update_sql_template(id):
        """更新 SQL 模板"""
        try:
            data = flask.request.json
            if not data:
                return jsonify({"type": "error", "error": "请提供 JSON 数据"})

            description = data.get('description')
            sql_template = data.get('sql_template')
            parameters_data = data.get('parameters')
            plotly_code = data.get('plotly_code')

            # 处理parameters字段
            if parameters_data is not None:
                # 如果parameters是列表或字典，转换为JSON字符串；如果已经是字符串，直接使用
                if isinstance(parameters_data, (list, dict)):
                    parameters = json.dumps(parameters_data, ensure_ascii=False)
                else:
                    parameters = parameters_data
            else:
                parameters = None

            success = sql_function_context.update_function(
                id=id,
                description=description,
                sql_template=sql_template,
                parameters=parameters,
                plotly_code=plotly_code
            )

            if success:
                return jsonify({
                    "type": "success",
                    "message": f"模板 {id} 更新成功"
                })
            else:
                return jsonify({
                    "type": "error",
                    "error": f"更新模板失败，可能模板 {id} 不存在"
                })

        except Exception as e:
            return jsonify({"type": "error", "error": f"更新模板失败: {str(e)}"})

    @app.route('/api/v0/sql_templates/<id>', methods=['DELETE'])
    def delete_sql_template(id):
        """删除 SQL 模板"""
        try:
            success = sql_function_context.delete_function(id=id)

            if success:
                return jsonify({
                    "type": "success",
                    "message": f"模板 {id} 删除成功"
                })
            else:
                return jsonify({
                    "type": "error",
                    "error": f"删除模板失败，可能模板 {id} 不存在"
                })

        except Exception as e:
            return jsonify({"type": "error", "error": f"删除模板失败: {str(e)}"})

    @app.route('/api/v0/similar_sql_templates', methods=['POST'])
    def search_sql_templates():
        """搜索相似的 SQL 模板"""
        try:
            data = flask.request.json
            if not data:
                return jsonify({"type": "error", "error": "请提供 JSON 数据"})
            
            query = data.get('query')
            if not query:
                return jsonify({"type": "error", "error": "请提供搜索查询"})

            templates = sql_function_context.search_similar_templates(query)
            
            # 为每个模板添加相似度分数（这里使用模拟数据，实际应该基于向量相似度计算）
            results = []
            for i, template in enumerate(templates):
                template_dict = template.copy() if isinstance(template, dict) else template.__dict__.copy()
                # 模拟相似度分数，实际应该基于语义相似度计算
                #template_dict['similarity'] = max(0.5, 1.0 - i * 0.1)
                results.append(template_dict)
            
            # 按相似度排序
            results.sort(key=lambda x: x.get('similarity', 0), reverse=True)

            # 使用json.dumps确保中文字符不被unicode编码
            response_data = {
                "type": "df",
                "df": results
            }
            response = flask.Response(
                json.dumps(response_data, ensure_ascii=False, indent=2),
                mimetype='application/json; charset=utf-8'
            )
            return response

        except Exception as e:
            return jsonify({"type": "error", "error": f"搜索模板失败: {str(e)}"})


    @app.route('/api/v0/generate_followup_questions', methods=['GET'])
    @requires_cache(['df', 'question', 'sql'])
    def generate_followup_questions(id: str, df, question, sql):
        return jsonify(
            {
                "type": "question_list", 
                "id": id,
                "questions": '{}',
                "header": "Here are some followup questions you can ask:"
            })

    @app.route('/api/v0/load_question', methods=['GET'])
    @requires_cache(['question', 'sql', 'df'])
    def load_question(id: str, question, sql, df):
        try:
            return jsonify(
                {
                    "type": "question_cache",
                    "id": id,
                    "question": question,
                    "sql": sql,
                    "df": df.head(10).to_json(orient='records'),
                    "fig": "{}",
                    "followup_questions": {}
                })
        except Exception as e:
            return jsonify({"type": "error", "error": str(e)})

    @app.route('/api/v0/get_question_history', methods=['GET'])
    def get_question_history():
        return jsonify({"type": "question_history", "questions": cache.get_all(field_list=['question']) })

    @app.route('/api/v0/generate_command', methods=['GET'])
    def generate_command_v4():
        question = flask.request.args.get('question')
        uuid = flask.request.args.get('uuid')
        type = flask.request.args.get('type')
        
        if question is None:
            return jsonify({"uuid": uuid, "type": type, "message": "没有提供问题"})
        
        try:
            uuid, type, message = generate_command_core(question, uuid, type)
            return jsonify({"uuid": uuid, "type": type, "message": message})
        except Exception as e:
            logger.error(f"命令生成失败: {e}")
            return jsonify({
                "uuid": uuid, 
                "type": "error", 
                "message": f"系统错误: {str(e)}"
            })

    @app.route('/api/v0/generate_diagnosis', methods=['GET'])
    def generate_diagnosis():
        question = flask.request.args.get('question')
        id = flask.request.args.get('id')
        if question is None:
            return jsonify({"id": id, "message": "没有提供问题"})
        
        id, message = generate_diagnosis_core(question, id)
        return jsonify({"id": id, "message": message})
        

    @app.route('/api/v0/generate_answer', methods=['GET'])
    def generate_answer():
        question = flask.request.args.get('question')
        id = flask.request.args.get('id', None)
        stream = flask.request.args.get('stream', 'false').lower() == 'true'
        
        if question is None:
            return jsonify({"type": "error", "error": "没有提供问题"})
        
        if id is None:
            id = cache.generate_id(question=question)
        
        type, result = generate_answer_core(question, id)
        return jsonify({"id": id, "type": type, "message": result})

    @app.route('/api/v0/generate_answer_multi_agent', methods=['GET'])
    def generate_answer_multi_agent():
        """
        多智能体版本的意图识别与分发接口
        
        采用协调者模式（Coordinator Pattern）：
        - 协调者 Agent 负责识别用户意图
        - 专家 Agent 负责具体任务处理
        - 每个专家有独立的工具集和处理逻辑
        
        参数：
            question: 用户问题（必填）
            id: 会话ID（可选，不提供则自动生成）
        
        返回：
            {
                "id": "会话ID",
                "type": "任务类型",
                "message": "处理结果"
            }
        
        任务类型：
            - sql: 数据查询分析
            - command: 设备控制
            - knowledge: 知识咨询
            - router: 菜单导航
            - diagnosis: 故障诊断
            - other: 其他/需要澄清
            - complete: 对话结束
        """
        question = flask.request.args.get('question')
        id = flask.request.args.get('id', None)
        
        if question is None:
            return jsonify({"type": "error", "error": "没有提供问题"})
        
        if id is None:
            id = cache.generate_id(question=question)
        
        try:
            # 调用多智能体系统处理
            task_type, result = generate_answer_core_multi_agent(question, id)
            
            return jsonify({
                "id": id,
                "type": task_type,
                "message": result
            })
            
        except Exception as e:
            logger.error(f"多智能体处理失败: {e}", exc_info=True)
            return jsonify({
                "id": id,
                "type": "error",
                "error": f"系统错误: {str(e)}"
            })

    # Dashboard API endpoints
    @app.route('/api/v0/charts', methods=['POST'])
    def save_chart():
        """保存图表"""
        try:
            data = flask.request.json
            if not data:
                return jsonify({"type": "error", "error": "请提供 JSON 数据"})
            
            title = data.get('title')
            chart_type = data.get('chart_type')
            chart_data = data.get('chart_data')
            question = data.get('question')
            sql = data.get('sql')
            
            if not all([title, chart_type, chart_data]):
                return jsonify({
                    "type": "error",
                    "error": "title, chart_type 和 chart_data 是必填字段"
                })
            
            chart_config = {
                'title': title,
                'chart_type': chart_type,
                'chart_config': chart_data,
                'data_config': chart_data,
                'question': question or '',
                'sql': sql or ''
            }
            
            chart_id = dashboard_service.save_chart(chart_config)
            
            return jsonify({
                "type": "success",
                "message": "图表保存成功",
                "chart_id": chart_id
            })
            
        except Exception as e:
            return jsonify({"type": "error", "error": f"保存图表失败: {str(e)}"})
    
    @app.route('/api/v0/charts', methods=['GET'])
    def get_charts():
        """获取图表列表"""
        try:
            charts = dashboard_service.get_charts()
            return jsonify({
                "type": "chart_list",
                "charts": charts
            })
        except Exception as e:
            return jsonify({"type": "error", "error": f"获取图表列表失败: {str(e)}"})
    
    @app.route('/api/v0/dashboards', methods=['POST'])
    def create_dashboard():
        """创建仪表板"""
        try:
            data = flask.request.json
            if not data:
                return jsonify({"type": "error", "error": "请提供 JSON 数据"})
            
            name = data.get('name')
            description = data.get('description', '')
            
            if not name:
                return jsonify({
                    "type": "error",
                    "error": "name 是必填字段"
                })
            
            dashboard_id = dashboard_service.create_dashboard(
                name=name,
                description=description
            )
            
            return jsonify({
                "type": "success",
                "message": "仪表板创建成功",
                "dashboard_id": dashboard_id
            })
            
        except Exception as e:
            return jsonify({"type": "error", "error": f"创建仪表板失败: {str(e)}"})
    
    @app.route('/api/v0/dashboards', methods=['GET'])
    def get_dashboards():
        """获取仪表板列表"""
        try:
            dashboards = dashboard_service.get_dashboards()
            return jsonify({
                "type": "dashboard_list",
                "dashboards": dashboards
            })
        except Exception as e:
            return jsonify({"type": "error", "error": f"获取仪表板列表失败: {str(e)}"})
    
    @app.route('/api/v0/dashboards/<dashboard_id>/charts', methods=['POST'])
    def add_chart_to_dashboard(dashboard_id):
        """添加图表到仪表板"""
        try:
            data = flask.request.json
            if not data:
                return jsonify({"type": "error", "error": "请提供 JSON 数据"})
            
            chart_id = data.get('chart_id')
            position_x = data.get('position_x', 0)
            position_y = data.get('position_y', 0)
            width = data.get('width', 6)
            height = data.get('height', 4)
            
            if not chart_id:
                return jsonify({
                    "type": "error",
                    "error": "chart_id 是必填字段"
                })
            
            position = {
                'x': position_x,
                'y': position_y,
                'width': width,
                'height': height
            }
            
            dashboard_service.add_chart_to_dashboard(
                dashboard_id=dashboard_id,
                chart_id=chart_id,
                position=position
            )
            
            success = True
            
            if success:
                return jsonify({
                    "type": "success",
                    "message": "图表添加到仪表板成功"
                })
            else:
                return jsonify({
                    "type": "error",
                    "error": "添加图表到仪表板失败"
                })
            
        except Exception as e:
            return jsonify({"type": "error", "error": f"添加图表到仪表板失败: {str(e)}"})
    
    @app.route('/api/v0/dashboards/<dashboard_id>', methods=['GET'])
    def get_dashboard(dashboard_id):
        """获取仪表板详情"""
        try:
            dashboard = dashboard_service.get_dashboard_with_charts(dashboard_id)
            if dashboard:
                response_data = {
                    "type": "dashboard_detail",
                    "dashboard": dashboard
                }
                response = flask.Response(
                    json.dumps(response_data, ensure_ascii=False, indent=2),
                    mimetype='application/json; charset=utf-8'
                )
                return response
            else:
                return jsonify({
                    "type": "error",
                    "error": "仪表板不存在"
                })
        except Exception as e:
            return jsonify({"type": "error", "error": f"获取仪表板详情失败: {str(e)}"})
    
    @app.route('/api/v0/dashboards/<dashboard_id>/layout', methods=['PUT'])
    def update_dashboard_layout(dashboard_id):
        """更新仪表板布局"""
        try:
            data = flask.request.json
            if not data:
                return jsonify({"type": "error", "error": "请提供 JSON 数据"})
            
            layout = data.get('layout')
            if not layout:
                return jsonify({
                    "type": "error",
                    "error": "layout 是必填字段"
                })
            
            success = dashboard_service.update_dashboard_layout(dashboard_id, layout)
            
            if success:
                return jsonify({
                    "type": "success",
                    "message": "仪表板布局更新成功"
                })
            else:
                return jsonify({
                    "type": "error",
                    "error": "更新仪表板布局失败"
                })
            
        except Exception as e:
            return jsonify({"type": "error", "error": f"更新仪表板布局失败: {str(e)}"})
    
    @app.route('/api/v0/charts/<chart_id>/title', methods=['PUT'])
    def update_chart_title(chart_id):
        """更新图表标题"""
        try:
            data = flask.request.json
            if not data:
                return jsonify({"type": "error", "error": "请提供 JSON 数据"})
            
            title = data.get('title')
            if not title:
                return jsonify({
                    "type": "error",
                    "error": "title 是必填字段"
                })
            
            success = dashboard_service.update_chart_title(chart_id, title)
            
            if success:
                return jsonify({
                    "type": "success",
                    "message": "图表标题更新成功"
                })
            else:
                return jsonify({
                    "type": "error",
                    "error": "更新图表标题失败，图表可能不存在"
                })
            
        except Exception as e:
            return jsonify({"type": "error", "error": f"更新图表标题失败: {str(e)}"})
    
    @app.route('/api/v0/dashboards/<dashboard_id>/charts/<chart_id>', methods=['DELETE'])
    def remove_chart_from_dashboard(dashboard_id, chart_id):
        """从仪表板删除图表"""
        try:
            dashboard_service.remove_chart_from_dashboard(dashboard_id, chart_id)
            
            return jsonify({
                "type": "success",
                "message": "图表已从仪表板删除"
            })
            
        except Exception as e:
            return jsonify({"type": "error", "error": f"删除图表失败: {str(e)}"})
    
    @app.route('/api/v0/dashboards/<dashboard_id>', methods=['PUT'])
    def update_dashboard(dashboard_id):
        """更新仪表板"""
        try:
            data = flask.request.json
            if not data:
                return jsonify({"type": "error", "error": "请提供 JSON 数据"})
            
            name = data.get('name')
            description = data.get('description')
            
            if not name:
                return jsonify({
                    "type": "error",
                    "error": "name 是必填字段"
                })
            
            success = dashboard_service.update_dashboard(
                dashboard_id=dashboard_id,
                name=name,
                description=description
            )
            
            if success:
                return jsonify({
                    "type": "success",
                    "message": "仪表板更新成功"
                })
            else:
                return jsonify({
                    "type": "error",
                    "error": "更新仪表板失败，仪表板可能不存在"
                })
            
        except Exception as e:
            return jsonify({"type": "error", "error": f"更新仪表板失败: {str(e)}"})
    
    @app.route('/api/v0/dashboards/<dashboard_id>', methods=['DELETE'])
    def delete_dashboard(dashboard_id):
        """删除仪表板"""
        try:
            success = dashboard_service.delete_dashboard(dashboard_id)
            
            if success:
                return jsonify({
                    "type": "success",
                    "message": "仪表板删除成功"
                })
            else:
                return jsonify({
                    "type": "error",
                    "error": "删除仪表板失败，仪表板可能不存在"
                })
            
        except Exception as e:
            return jsonify({"type": "error", "error": f"删除仪表板失败: {str(e)}"})
    
    @app.route('/api/v0/charts/<chart_id>', methods=['PUT'])
    def update_chart(chart_id):
        """更新图表"""
        try:
            data = flask.request.json
            if not data:
                return jsonify({"type": "error", "error": "请提供 JSON 数据"})
            
            title = data.get('title')
            description = data.get('description')
            chart_type = data.get('chart_type')
            chart_data = data.get('chart_data')
            question = data.get('question')
            sql = data.get('sql')
            
            # 构建更新数据
            update_data = {}
            if title is not None:
                update_data['title'] = title
            if description is not None:
                update_data['description'] = description
            if chart_type is not None:
                update_data['chart_type'] = chart_type
            if chart_data is not None:
                update_data['chart_config'] = chart_data
                update_data['data_config'] = chart_data
            if question is not None:
                update_data['question'] = question
            if sql is not None:
                update_data['sql'] = sql
            
            if not update_data:
                return jsonify({
                    "type": "error",
                    "error": "请提供要更新的字段"
                })
            
            success = dashboard_service.update_chart(chart_id, update_data)
            
            if success:
                return jsonify({
                    "type": "success",
                    "message": "图表更新成功"
                })
            else:
                return jsonify({
                    "type": "error",
                    "error": "更新图表失败，图表可能不存在"
                })
            
        except Exception as e:
            return jsonify({"type": "error", "error": f"更新图表失败: {str(e)}"})
    
    @app.route('/api/v0/charts/<chart_id>', methods=['DELETE'])
    def delete_chart(chart_id):
        """删除图表"""
        try:
            success = dashboard_service.delete_chart(chart_id)
            
            if success:
                return jsonify({
                    "type": "success",
                    "message": "图表删除成功"
                })
            else:
                return jsonify({
                    "type": "error",
                    "error": "删除图表失败，图表可能不存在"
                })
            
        except Exception as e:
            return jsonify({"type": "error", "error": f"删除图表失败: {str(e)}"})

    @app.route('/api/v0/cache/stats', methods=['GET'])
    def get_cache_stats():
        """获取缓存统计信息"""
        try:
            if hasattr(cache, 'get_stats'):
                stats = cache.get_stats()
                return jsonify({
                    "type": "success",
                    "stats": stats
                })
            else:
                return jsonify({
                    "type": "error",
                    "error": "Cache implementation does not support stats"
                })
        except Exception as e:
            return jsonify({"type": "error", "error": f"获取缓存统计失败: {str(e)}"})
    
    @app.route('/api/v0/cache/clear', methods=['POST'])
    def clear_cache():
        """清空所有缓存（需要管理员权限）"""
        try:
            if hasattr(cache, 'clear'):
                cache.clear()
                return jsonify({
                    "type": "success",
                    "message": "缓存已清空"
                })
            else:
                return jsonify({
                    "type": "error",
                    "error": "Cache implementation does not support clear"
                })
        except Exception as e:
            return jsonify({"type": "error", "error": f"清空缓存失败: {str(e)}"})
    
    @app.route('/api/v0/cache/cleanup', methods=['POST'])
    def cleanup_cache():
        """清理过期缓存"""
        try:
            if hasattr(cache, '_cleanup_expired'):
                cache._cleanup_expired()
                return jsonify({
                    "type": "success",
                    "message": "过期缓存已清理"
                })
            else:
                return jsonify({
                    "type": "error",
                    "error": "Cache implementation does not support cleanup"
                })
        except Exception as e:
            return jsonify({"type": "error", "error": f"清理缓存失败: {str(e)}"})

    @app.route('/')
    @app.route('/vanna')
    @app.route('/vanna/')
    def root():
        return app.send_static_file('index.html')